// GraphRegAllocator.h
// Defines the class GraphRegAllocator
#ifndef GRAPHREGALLOCATOR_H
#define GRAPHREGALLOCATOR_H

#include "crossbit/common.h"
#include "crossbit/RegAllocator.h"
#include <map>
#include <set>
#include <deque>
//#include <vector>

namespace crossbit {

    //class TBlock;
    //class VInst;

 class GraphRegAllocator : public RegAllocator {
	 public:
	  GraphRegAllocator( XTUint8 num_regs, CBOfSpillIn cb_spill_in, CBOfSpillOut cb_spill_out, CBOfRegToReg cb_regtoreg):RegAllocator(num_regs, cb_spill_in, cb_spill_out, cb_regtoreg){}
	  virtual ~GraphRegAllocator(){}
		 virtual void init(VBlock * vblock);
	  virtual XTRegNum regAlloc(XTRegNum vreg, RegAccessMode mode);
	  virtual XTRegNum regAllocForce(XTRegNum vreg, XTRegNum expect, RegAccessMode mode);
   virtual XTRegNum regAllocExpect(XTRegNum vreg, XTUint8 reg_mask, RegAccessMode mode);
	  virtual XTRegNum regAllocForceExcept(XTRegNum vreg, XTRegNum except, RegAccessMode mode);
	  virtual void regAllocReserve(XTRegNum reg);
	  virtual void regAllocRelease(XTRegNum reg);

	 private:
		 void collectGraphInfo(VBlock * vblock);
   void interfereGraphGen();//czj 2009.4.6
   void regPreAllocAllVars(XTInt32 graph_dim, XTInt32 reg_num);//czj 2009.4.6
	          
   virtual void incrementVinstSeq()
   {
    vinst_seq++;
    for(XTRegNum i=0;i<ra_num_of_reg;i++)
    {
     if(ra_reg_table[i].status==ALLOCATED)
     {
      XTRegNum vreg=ra_reg_table[i].mapped_to;
      //printf("This is %d ALLOCATED with %d\n",i,vreg);
      ra_vreg_spilledIn[vreg]=true;
     }
    }
   }
            
   virtual void regSpillIn(XTRegNum vreg,XTRegNum treg);
		 virtual XTRegNum regSpillOut(XTRegNum vreg);
 
   //add by czj 2008-5-15
   typedef std::set<XTRegNum> RegList;
   typedef std::deque<RegList> RegLists;
   RegLists reg_lists;
		
		 const	static  XTInt32 SAVEALLOC = 0x08;        
		 const static  XTInt32 VREG_MAX_NUM = 50;        
   const static XTInt32 X86_TREG_NUM=8;
		 
   XTInt32 size;
   XTInt32 lower_bound;
   XTInt32 upper_bound;
		 XTInt32 canGraph;
   
   XTInt32 reg4vars[VREG_MAX_NUM];
		 RegUsage ra_reg_table[X86_TREG_NUM];
   bool ra_vreg_spilledIn[VREG_MAX_NUM];//whether Vreg is mappedto a treg.
	  XTInt32 interfere_graph[VREG_MAX_NUM][VREG_MAX_NUM];
   XTInt32 vreg_count[VREG_MAX_NUM];
   XTInt32 vreg_degree[VREG_MAX_NUM];
 };  
}

#endif
